package org.hcyspartnoc.demo.utils;


import com.alibaba.fastjson2.JSON;
import com.wechat.pay.java.core.util.PemUtil;
import okhttp3.*;
import org.hcyspartnoc.demo.common.core.configuration.WeiXinConfiguration;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.Base64;

@Component
public class WeiXinUtils {
    private static final MediaType JSON_FORMAT = MediaType.get("application/json; charset=utf-8");

    private static WeiXinConfiguration weiXinConfiguration;

    @Resource
    public void setWeiXinConfiguration(WeiXinConfiguration weiXinConfiguration) {
        WeiXinUtils.weiXinConfiguration = weiXinConfiguration;
    }

    public static String generateOpenIdUrl(String jsCode) {
        return weiXinConfiguration.getOpenId().getBaseUrl() +
                "?appid=" + weiXinConfiguration.getAppId() +
                "&secret=" + weiXinConfiguration.getAppSecret() +
                "&js_code=" + jsCode +
                "&grant_type=" + weiXinConfiguration.getOpenId().getGrantType();
    }

    public static String getSessionKeyOrOpenId(String code) {
        String url = generateOpenIdUrl(code);
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(url)
                .get()
                .build();
        try (Response res = client.newCall(request).execute()) {
            if (res.isSuccessful()) {
                if (res.body() != null) {
                    String resBody = res.body().string();
                    System.out.println(resBody);
                    return JSON.parseObject(resBody).getString("openid");
                }
            }
        } catch (Exception ignore) {
            System.out.println(ignore);
        }
        return null;
    }


    public static String getSign(String signatureStr, String privateKey) throws InvalidKeyException, NoSuchAlgorithmException, SignatureException, IOException, URISyntaxException {
        //replace 根据实际情况，不一定都需要
        String replace = privateKey.replace("\\n", "\n");
        PrivateKey merchantPrivateKey = PemUtil.loadPrivateKeyFromPath(replace);
        Signature sign = Signature.getInstance("SHA256withRSA");
        sign.initSign(merchantPrivateKey);
        sign.update(signatureStr.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(sign.sign());
    }

//    public WxPayRespVO createOrder(int centsOfAmount, String outTradeNo, OrderTypeEnum orderTypeEnum) throws WeiXinException {
//        try {
//            // 最低金额为1分
//            centsOfAmount = Math.max(centsOfAmount, 1);
//            // 使用自动更新平台证书的RSA配置
//            // 一个商户号只能初始化一个配置，否则会因为重复的下载任务报错
//            Config config =
//                    new RSAAutoCertificateConfig.Builder()
//                            .merchantId(weiXinConfiguration.getMch().getId())
//                            .privateKeyFromPath(weiXinConfiguration.getMch().getKeyPath())
//                            .merchantSerialNumber(weiXinConfiguration.getMch().getSerialNo())
//                            .apiV3Key(weiXinConfiguration.getMch().getApiKey())
//                            .build();
//            // 构建service
//            JsapiService service = new JsapiService.Builder().config(config).build();
//            PrepayRequest request = new PrepayRequest();
//            Amount amount = new Amount();
//            amount.setTotal(centsOfAmount);
//            request.setAmount(amount);
//            request.setAppid(weiXinConfiguration.getAppId());
//            request.setMchid(weiXinConfiguration.getMch().getId());
//            request.setDescription(outTradeNo);
//            request.setNotifyUrl(weiXinConfiguration.getMch().getNotifyUrl());
//            request.setOutTradeNo(outTradeNo);
//            request.setAttach(orderTypeEnum.getCode().toString());
//
//            // 通过上下文获取当前用户
//            SysUserPo currentUser = BaseContextHolder.getContext().getBaseCurrentUser();
//            Payer payer = new Payer();
//            payer.setOpenid(currentUser.getOpenId());
//            request.setPayer(payer);
//
//            // 调用下单方法，得到应答
//            PrepayResponse response = service.prepay(request);
//
//            WxPayRespVO vo = new WxPayRespVO();
//            Long timeStamp = System.currentTimeMillis() / 1000;
//            vo.setTimeStamp(timeStamp);
//            String substring = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
//            vo.setNonceStr(substring);
//            String signatureStr = Stream.of(weiXinConfiguration.getAppId(), String.valueOf(timeStamp), substring, "prepay_id=" + response.getPrepayId())
//                    .collect(Collectors.joining("\n", "", "\n"));
//            String sign = WeiXinUtils.getSign(signatureStr, weiXinConfiguration.getMch().getKeyPath());
//            vo.setPaySign(sign);
//            vo.setPrepayId(response.getPrepayId());
//            return vo;
//        } catch (RuntimeException | NoSuchAlgorithmException | SignatureException | IOException | URISyntaxException |
//                 InvalidKeyException e) {
//            System.out.println(e.getMessage());
//            throw new WeiXinException(WeiXinException.CREAT_ORDER_FAIL);
//        }
//    }
//
//    public boolean closeOrder(ServicePaymentPo servicePaymentPo) {
//        try {
//            String url = "https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/" + servicePaymentPo.getOrderId() + "/close";
//            HashMap<String, String> data = new HashMap<>();
//            data.put("mchid", weiXinConfiguration.getMch().getId());
//            String token = getToken("POST", HttpUrl.parse(url), JSON.toJSONString(data));
//            OkHttpClient client = new OkHttpClient();
//            RequestBody body = RequestBody.create(JSON.toJSONString(data), JSON_FORMAT);
//            Request request = new Request.Builder()
//                    .addHeader("Authorization", schema + " " + token)
//                    .addHeader("Accept", "application/json")
//                    .addHeader("Content-Type", "application/json")
//                    .url(url) // 注意：这里可能是错误的URL，请替换为实际的URL
//                    .post(body)
//                    .build();
//            try (Response response = client.newCall(request).execute()) {
//                return response.isSuccessful();
//            } catch (IOException ignore) {
//                return false;
//            }
//        } catch (Exception ignore) {
//            return false;
//        }
//    }

    // Authorization: <schema> <token>
// GET - getToken("GET", httpurl, "")
// POST - getToken("POST", httpurl, json)
    private static final String schema = "WECHATPAY2-SHA256-RSA2048";

    String getToken(String method, HttpUrl url, String body) throws UnsupportedEncodingException, SignatureException, NoSuchAlgorithmException, InvalidKeyException {
        String nonceStr = "your nonce string";
        long timestamp = System.currentTimeMillis() / 1000;
        String message = buildMessage(method, url, timestamp, nonceStr, body);
        String signature = sign(message.getBytes("utf-8"));
        return "mchid=\"" + weiXinConfiguration.getMch().getId() + "\","
                + "nonce_str=\"" + nonceStr + "\","
                + "timestamp=\"" + timestamp + "\","
                + "serial_no=\"" + weiXinConfiguration.getMch().getSerialNo() + "\","
                + "signature=\"" + signature + "\"";
    }

    String sign(byte[] message) throws SignatureException, NoSuchAlgorithmException, InvalidKeyException {
        Signature sign = Signature.getInstance("SHA256withRSA");
        String replace = weiXinConfiguration.getMch().getKeyPath().replace("\\n", "\n");
        PrivateKey merchantPrivateKey = PemUtil.loadPrivateKeyFromPath(replace);
        sign.initSign(merchantPrivateKey);
        sign.update(message);
        return Base64.getEncoder().encodeToString(sign.sign());
    }

    String buildMessage(String method, HttpUrl url, long timestamp, String nonceStr, String body) {
        String canonicalUrl = url.encodedPath();
        if (url.encodedQuery() != null) {
            canonicalUrl += "?" + url.encodedQuery();
        }
        return method + "\n"
                + canonicalUrl + "\n"
                + timestamp + "\n"
                + nonceStr + "\n"
                + body + "\n";
    }
}
